/*
 * REFSyncBlock.h
 *
 *  Created on: Apr 19, 2013
 *      Author: Lucifer
 */

#ifndef __BFX_SYNCBLOCK_H__
#define __BFX_SYNCBLOCK_H__

namespace BFX
{

#ifndef	INFINITE
#define	INFINITE	0xFFFFFFFF
#endif	//	INFINITE

/**
 * Provides a mechanism that can be synchronizes access.
 */
class SyncBlock
{
    friend class REFThread;
public:
    /**
     * Initializes a new instance of BFX::SyncBlock.
     * @return
     */
    SyncBlock();
    /**
     * Destroys a instance of BFX::SyncBlock
     * @return
     */
	virtual ~SyncBlock();

	/**
	 * Releases the lock on an object and blocks the current thread until it reacquires the lock. If the specified time-out interval
	 * elapses, the thread enters the ready queue.
	 * @param[in] nMilliseconds The number of milliseconds to wait before the thread enters the ready queue.
	 * @return True if the lock was reacquired before the specified time elapsed; False if the lock was reacquired after the specified time
	 * 		elapsed. The method does not return until the lock is reacquired.
	 */
    bool Wait(INT32 nMilliseconds = INFINITE);
    /**
     * Notifies a thread in the waiting queue of a change in the lock state.
     */
    void Signal();
    /**
     * Notifies all waiting threads of a change in the object's state.
     */
    void SignalAll();

    /**
     * Acquires an exclusive lock on the specified object.
     */
	void EnterMonitor();

	/**
	 * Attempts to acquire an exclusive lock on the specified object.
	 * @param[in] nMilliseconds The number of milliseconds to wait for the lock. Default value is 0; Specially -1 equivalent to BFX::SyncBlock::EnterMonitor()
	 * @return True if the current thread acquires the lock; otherwise, false.
	 */
	bool TryEnterMonitor(INT32 nMilliseconds = 0);
	/**
	 * Releases an exclusive lock on the specified object.
	 */
	void LeaveMonitor();

protected:
	// A silence version of our BFX::SyncBlock::Wait(). Just return the timeout state without thread alertable exception.
    bool WaitNoAlert(INT32 nMilliseconds = INFINITE);

#ifdef	_WIN32
    // Event queue helpers.
	void EnqueueWaitEvent(HANDLE hWaitEvent);
	HANDLE DequeueWaitEvent();

private:
	Mutex		m_mutexWait;
	Mutex		m_lockEvents;
	List<HANDLE>	m_listEvents;

	INT32	m_nLockCount;
#else	//	_WIN32

private:

	pthread_mutex_t	m_hMutex;
    pthread_cond_t	m_hCond;
#endif	//	!_WIN32
	long	m_nOwningThreadId;

public:
	typedef ObjectHolderT<SyncBlock, &SyncBlock::EnterMonitor, &SyncBlock::LeaveMonitor> SyncLock;
};

} /* namespace BFX */
#endif /* __BFX_SYNCBLOCK_H__ */
